package com.my.ruyi.schedule;

import java.util.Properties;

import org.quartz.spi.JobFactory;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;

@Configuration
public class QuartzConfig {
	public static final String QUARTZ_PROPERTIES_PATH = "quartz.properties";
	
	/**
	 * job工厂
	 * @param applicationContext
	 * @return
	 */
	@Bean
	public JobFactory jobFactory(ApplicationContext applicationContext) {
		AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
		jobFactory.setApplicationContext(applicationContext);
		return jobFactory;
	}
	
	/**
	 * 调度工厂类
	 * @param jobFactory
	 * @return
	 * @throws Exception
	 */
	@Bean
	public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory) throws Exception {
		SchedulerFactoryBean factoryBean = new SchedulerFactoryBean();
		factoryBean.setAutoStartup(true);
		factoryBean.setJobFactory(jobFactory);
		// quartz属性
		factoryBean.setQuartzProperties(quartzProperties());
		return factoryBean;
	}
	
	@Bean
	public Properties quartzProperties() throws Exception{
		PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
		// 设置quartz属性的文件路径
		propertiesFactoryBean.setLocation(new ClassPathResource(QUARTZ_PROPERTIES_PATH));
		propertiesFactoryBean.afterPropertiesSet();
		return propertiesFactoryBean.getObject();
	}
	
	public static class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware{
		// 将不需要序列化的属性前添加关键字transient，序列化对象的时候，这个属性就不会序列化到指定的目的地中。
		private transient AutowireCapableBeanFactory beanFactory;
		
		@Override
		public void setApplicationContext(final ApplicationContext arg0) throws BeansException {
			beanFactory = arg0.getAutowireCapableBeanFactory();
		}

		@Override
		protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
			final Object jobInstance = super.createJobInstance(bundle);
			beanFactory.autowireBean(jobInstance);
			return jobInstance;
		}
		
	}
}
